/* @flow */

import config from '../config'
import { initUse } from './use'
import { initMixin } from './mixin'
import { initExtend } from './extend'
import { initAssetRegisters } from './assets'
import { set, del } from '../observer/index'
import { ASSET_TYPES } from 'shared/constants'
import builtInComponents from '../components/index'

import {
  warn,
  extend,
  nextTick,
  mergeOptions,
  defineReactive
} from '../util/index'

export function initGlobalAPI (Vue: GlobalAPI) {
  // config
  const configDef = {}
  configDef.get = () => config
  if (process.env.NODE_ENV !== 'production') {
    configDef.set = () => {
      warn(
        'Do not replace the Vue.config object, set individual fields instead.'
      )
    }
  }
  /**
   * 第一个参数:目标对象
   * 第二个参数:需要定义的属性或方法的名字
   * 第三个参数:目标属性所拥有的特性。（descriptor）
   * alue:属性的值(不用多说了)
    * writable：如果为false，属性的值就不能被重写,只能为只读了
    * configurable：总开关，一旦为false，就不能再设置他的（value，writable，configurable）
    * enumerable：是否能在for…in循环中遍历出来或在Object.keys中列举出来。
    * get：
    * set：
   */
  Object.defineProperty(Vue, 'config', configDef)

  // exposed util methods.
  // NOTE: these are not considered part of the public API - avoid relying on
  // them unless you are aware of the risk.
  Vue.util = {
    warn,
    extend,
    mergeOptions,
    defineReactive
  }
  // 绑定全局API——Vue.set，Vue.delete，Vue.nextTick
  Vue.set = set
  Vue.delete = del
  Vue.nextTick = nextTick

  Vue.options = Object.create(null)
  ASSET_TYPES.forEach(type => { // 添加components,directives,filters
    Vue.options[type + 's'] = Object.create(null)
  })

  // this is used to identify the "base" constructor to extend all plain-object
  // components with in Weex's multi-instance scenarios.
  // 指向Vue本身的 _base
  Vue.options._base = Vue

  // 把builtInComponents里面的属性添加到Vue.options.components里面
  extend(Vue.options.components, builtInComponents)

  // 初始化Vue.extend，Vue.mixin，Vue.extend
  initUse(Vue)
  initMixin(Vue)
  initExtend(Vue)
  // AssetRegisters就是component，directive，filter三者
  initAssetRegisters(Vue)
}
